home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / net / netCode.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  29KB  |  1,091 lines

  1. /* 
  2.  * netCode.c --
  3.  *
  4.  *    Various routines for initialzation, input and output.
  5.  *
  6.  *
  7.  * Copyright 1987 Regents of the University of California
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/net/netCode.c,v 9.11 92/06/03 22:47:50 voelker Exp $ SPRITE (Berkeley)";
  19. #endif
  20.  
  21. #include <sprite.h>
  22. #include <list.h>
  23. #include <net.h>
  24. #include <netInt.h>
  25. #include <devNet.h>
  26. #include <string.h>
  27. #include <sync.h>
  28. #include <dbg.h>
  29. #include <machMon.h>
  30. #include <netInet.h>
  31.  
  32. /*
  33.  * Network configuration table defined by machine dependent code.
  34.  */
  35. extern Net_Interface    netConfigInterfaces[];
  36. extern int        netNumConfigInterfaces;
  37. Net_Interface        *netInterfaces[NET_MAX_INTERFACES];
  38. int            netNumInterfaces;
  39.  
  40. Net_Address         netZeroAddress;
  41. int            net_NetworkHeaderSize[NET_NUM_NETWORK_TYPES];
  42.  
  43. #define    INC_BYTES_SENT(gatherPtr, gatherLength) { \
  44.     register    Net_ScatterGather    *gathPtr; \
  45.     int                    i; \
  46.     net_EtherStats.bytesSent += sizeof(Net_EtherHdr); \
  47.     for (i = gatherLength, gathPtr = gatherPtr; i > 0; i--, gathPtr++) { \
  48.         net_EtherStats.bytesSent += gathPtr->length; \
  49.     } \
  50.     }
  51. /*
  52.  * Macro to swap the fragOffset field.
  53.  */
  54. #define SWAP_FRAG_OFFSET_HOST_TO_NET(ptr) { \
  55.     unsigned short    *shortPtr; \
  56.     shortPtr = ((unsigned short *)&ptr->ident) + 1; \
  57.     *shortPtr = Net_HostToNetShort(*shortPtr); \
  58.  
  59. #define SWAP_FRAG_OFFSET_NET_TO_HOST(ptr) { \
  60.     unsigned short    *shortPtr; \
  61.     shortPtr = ((unsigned short *)&ptr->ident) + 1; \
  62.     *shortPtr = Net_NetToHostShort(*shortPtr); \
  63.  
  64. int netDebug = FALSE;
  65. /* Boolean    ultra = FALSE; */
  66.  
  67. static void NetAddStats _ARGS_((Net_Stats *aPtr, Net_Stats *bPtr, 
  68.             Net_Stats *sumPtr));
  69. static void EnterDebugger _ARGS_((Net_Interface *interPtr, Address packetPtr,
  70.                 int packetLength));
  71.  
  72. /*
  73.  *----------------------------------------------------------------------
  74.  *
  75.  * Net_Init --
  76.  *
  77.  *    Initialize the network module data structures.
  78.  *
  79.  * Results:
  80.  *    None.
  81.  *
  82.  * Side effects:
  83.  *    None.
  84.  *
  85.  *----------------------------------------------------------------------
  86.  */
  87.  
  88. void
  89. Net_Init()
  90. {
  91.     register int i;
  92.     char buffer[100];
  93.     ReturnStatus status;
  94.     int        counter[NET_NUM_NETWORK_TYPES];
  95.     Net_Interface    *interPtr;
  96.     int            j;
  97.  
  98.     NetEtherInit();
  99.  
  100.     for (i = 0; i < NET_NUM_NETWORK_TYPES; i++) {
  101.     counter[i] = 0;
  102.     }
  103.  
  104.     /*
  105.      * Determine the number and kind of network interfaces by calling
  106.      * each network interface initialization procedure.
  107.      */
  108.     bzero((char *) &netZeroAddress, sizeof(Net_Address));
  109.     netNumInterfaces = 0;
  110.     for (i = 0 ; i<netNumConfigInterfaces ; i++) {
  111.     interPtr = &netConfigInterfaces[i];
  112.     interPtr->flags = 0;
  113.     for (j = 0; j < NET_MAX_PROTOCOLS; j++) {
  114.         bzero((char *) &interPtr->netAddress[j], sizeof(Net_Address));
  115.     }
  116.     (void) sprintf(buffer, "NetOutputMutex:%d", i);
  117.     Sync_SemInitDynamic(&interPtr->syncOutputMutex, 
  118.                 strdup(buffer));
  119.     (void) sprintf(buffer, "NetMutex:%d", i);
  120.     Sync_SemInitDynamic(&interPtr->mutex, strdup(buffer));
  121.     status = (interPtr->init)(interPtr);
  122.     if (status == SUCCESS) {
  123.         netInterfaces[netNumInterfaces] = interPtr;
  124.         netNumInterfaces++;
  125.         interPtr->packetProc = NILPROC;
  126.         interPtr->devNetData = (ClientData) NIL;
  127.         interPtr->number = counter[interPtr->netType];
  128.         counter[interPtr->netType]++;
  129.     } 
  130.     }
  131.     net_NetworkHeaderSize[NET_NETWORK_ETHER] = sizeof(Net_EtherHdr);
  132.     net_NetworkHeaderSize[NET_NETWORK_ULTRA] = sizeof(Net_UltraHeader);
  133.     net_NetworkHeaderSize[NET_NETWORK_FDDI] = sizeof(Net_FDDIHdr);
  134.     Net_ArpInit();
  135.     return;
  136. }
  137.  
  138. /*
  139.  *----------------------------------------------------------------------
  140.  *
  141.  * Net_Bin --
  142.  *
  143.  *    Bin various memory sizes allocated by the net module.
  144.  *
  145.  * Results:
  146.  *    None.
  147.  *
  148.  * Side effects:
  149.  *    Calls Mem_Bin to optimize memory allocation.
  150.  *
  151.  *----------------------------------------------------------------------
  152.  */
  153.  
  154. void
  155. Net_Bin()
  156. {
  157.     register int inter;
  158.     for (inter = 0 ; inter < netNumInterfaces ; inter++) {
  159.     Mem_Bin(netInterfaces[inter]->maxBytes);
  160.     }
  161.     return;
  162. }
  163.  
  164. /*
  165.  *----------------------------------------------------------------------
  166.  *
  167.  * Net_GatherCopy --
  168.  *
  169.  *    Copy all of the data pointed to by the scatter/gather array into
  170.  *    the destination.
  171.  *
  172.  * Results:
  173.  *    None.
  174.  *
  175.  * Side effects:
  176.  *    None.
  177.  *
  178.  *----------------------------------------------------------------------
  179.  */
  180.  
  181. void
  182. Net_GatherCopy(scatterGatherPtr, scatterGatherLength, destAddr)
  183.     register    Net_ScatterGather *scatterGatherPtr;
  184.     int                    scatterGatherLength;
  185.     register    Address          destAddr;
  186. {
  187.     int i;
  188.     int soFar = 0;
  189.  
  190.     for (i = 0; i < scatterGatherLength; i++, scatterGatherPtr++) {
  191.     if (scatterGatherPtr->length == 0) {
  192.         continue;
  193.     }
  194.  
  195.     bcopy((Address) scatterGatherPtr->bufAddr, 
  196.          (Address) &(destAddr[soFar]), 
  197.          scatterGatherPtr->length);
  198.     soFar += scatterGatherPtr->length;
  199.     }
  200.     return;
  201. }
  202.  
  203.  
  204.  
  205. /*
  206.  *----------------------------------------------------------------------
  207.  *
  208.  * Net_Reset --
  209.  *
  210.  *    Reset the network interface.
  211.  *
  212.  * Results:
  213.  *    None.
  214.  *
  215.  * Side effects:
  216.  *    Reinitializes the network controller..
  217.  *
  218.  *----------------------------------------------------------------------
  219.  */
  220. void
  221. Net_Reset(interPtr)
  222.     Net_Interface    *interPtr;
  223. {
  224.     interPtr->reset(interPtr);
  225. }
  226.  
  227.  
  228. /*
  229.  *----------------------------------------------------------------------
  230.  *
  231.  * Net_Output --
  232.  *
  233.  *    Send a packet to a host identified by a Sprite Host ID.
  234.  *
  235.  * Results:
  236.  *    SUCCESS     - the operation was successful.
  237.  *    FAILURE        - there was no route to the host or 
  238.  *              the Sprite host ID was bad or 
  239.  *              an unknown route type was found.
  240.  *
  241.  * Side effects:
  242.  *    Sends the packet.
  243.  *    If no route has been established to the SpriteID then the
  244.  *    Address Resolution Protocol (ARP) is invoked to find the
  245.  *    physical address corresponding to the SpriteID.
  246.  *
  247.  *----------------------------------------------------------------------
  248.  */
  249.  
  250. ReturnStatus
  251. Net_Output(spriteID, gatherPtr, gatherLength, mutexPtr, routePtr)
  252.     int spriteID;            /* Host to which to send the packet */
  253.     Net_ScatterGather *gatherPtr;    /* Specifies buffers containing the
  254.                      * pieces of the packet The first
  255.                      * element of gatherPtr is assumed to 
  256.                      * be a buffer large enought to 
  257.                      * format any protocol headers
  258.                      * we need. */
  259.     int gatherLength;            /* Number of elements in gatherPtr[] */
  260.     Sync_Semaphore *mutexPtr;        /* Mutex that is released during the
  261.                      * ARP transaction (if needed).  This
  262.                      * doesn't mess up the caller because
  263.                      * its packet isn't output until
  264.                      * the ARP completes anyway */
  265.     Net_Route    *routePtr;        /* If non-NIL then used as the route
  266.                      * to send the packet. */
  267. {
  268.     Net_Interface    *interPtr;
  269.     Boolean        ourRoute = FALSE;
  270.     ReturnStatus    status;
  271.  
  272.     if (spriteID < 0 || spriteID >= NET_NUM_SPRITE_HOSTS) {
  273.     return(NET_UNREACHABLE_NET);
  274.     }
  275.  
  276.     /*
  277.      * Check for a route to the indicated host.  Use ARP to find it if needed.
  278.      */
  279.     if (routePtr == (Net_Route *) NIL) {
  280.     ourRoute = TRUE;
  281.     routePtr = Net_IDToRoute(spriteID, 0, TRUE, mutexPtr, 0);
  282.     if (routePtr == (Net_Route *)NIL) {
  283.         return(NET_UNREACHABLE_NET);
  284.     }
  285.     }
  286.     interPtr = routePtr->interPtr;
  287.     switch(routePtr->protocol) {
  288.     case NET_PROTO_RAW : {
  289.         /*
  290.          * The first gather buffer contains the protocol header for
  291.          * which we have none for the ethernet.
  292.          */
  293.         gatherPtr->length = 0;     
  294.         gatherPtr->done = FALSE;
  295.         gatherPtr->mutexPtr = mutexPtr;
  296.         status = (interPtr->output) (interPtr, 
  297.             routePtr->headerPtr[NET_PROTO_RAW], 
  298.             gatherPtr, gatherLength, TRUE, &status);
  299.         if (status == SUCCESS) {
  300.             while (!gatherPtr->done && 
  301.             mutexPtr != (Sync_Semaphore *)NIL) {
  302.             (void) Sync_SlowMasterWait((unsigned int)mutexPtr, 
  303.                 mutexPtr, 0);
  304.             }
  305.         }
  306.         break;
  307.         }
  308.     case NET_PROTO_INET: {
  309.         /*
  310.          * For the INET routes we must fill in the ipHeader in the 
  311.          * first buffer of the gather array. 
  312.          */
  313.         register Net_IPHeader        *ipHeaderPtr;
  314.         register unsigned int length;
  315.         register Net_ScatterGather    *gathPtr;
  316.         register int     i; 
  317.  
  318.         /*
  319.          * Compute the length of the gather vector. 
  320.          */
  321.         length = sizeof(Net_IPHeader);
  322.         gathPtr = gatherPtr + 1;
  323.         for (i = 1; i < gatherLength;  i++, gathPtr++){
  324.             length += gathPtr->length; 
  325.         }
  326.  
  327.  
  328.         /*
  329.          * Fill the  ipHeader into the first element of the 
  330.          * scatter/gather from the template stored in the route
  331.          * data.
  332.          */
  333.         gatherPtr->length = sizeof(Net_IPHeader);
  334.         ipHeaderPtr = (Net_IPHeader *) gatherPtr->bufAddr;
  335.         gatherPtr->done = FALSE;
  336.         gatherPtr->mutexPtr = mutexPtr;
  337.  
  338.         *ipHeaderPtr = *(Net_IPHeader *) 
  339.                     routePtr->headerPtr[NET_PROTO_INET];
  340.         /*
  341.          * Update length and checksum. The template 
  342.          * ipHeaderPtr->checksum should contain the 16 bit sum of 
  343.          * the IP header with totalLen set to zero. We add the
  344.          * new total length and convert into one-complement.
  345.          * See Net_InetChecksum().
  346.          */
  347.         length = Net_HostToNetShort(length);
  348.         ipHeaderPtr->totalLen = length;
  349.  
  350.         length = ipHeaderPtr->checksum + length;
  351.         ipHeaderPtr->checksum = ~(length + (length >> 16));
  352.  
  353.         status = (interPtr->output)(interPtr, 
  354.             routePtr->headerPtr[NET_PROTO_RAW], gatherPtr, 
  355.             gatherLength, FALSE, &status);
  356.         if (status == SUCCESS) {
  357.             while (!gatherPtr->done && 
  358.             mutexPtr != (Sync_Semaphore *)NIL) {
  359.             (void) Sync_SlowMasterWait((unsigned int)mutexPtr, 
  360.                     mutexPtr, 0);
  361.             }
  362.         }
  363.         break;
  364.         }
  365.     default:
  366.         printf("Warning: Net_Output: unsupported route protocol: %x\n", 
  367.             routePtr->protocol);
  368.         panic(NIL);
  369.         status = FAILURE;
  370.     }
  371.     if (ourRoute) {
  372.     Net_ReleaseRoute(routePtr);
  373.     }
  374.     return status;
  375. }
  376.  
  377.  
  378.  
  379. /*
  380.  *----------------------------------------------------------------------
  381.  *
  382.  * Net_RawOutput --
  383.  *
  384.  *    Send a packet directly onto the network.
  385.  *
  386.  * Results:
  387.  *    SUCCESS if the packet made it as far as the network interface,
  388.  *    a failure code otherwise.  SUCCESS does not imply that the
  389.  *    packet was actually sent because the interface could have
  390.  *    rejected it.
  391.  *
  392.  * Side effects:
  393.  *    None.
  394.  *
  395.  *----------------------------------------------------------------------
  396.  */
  397.  
  398. ReturnStatus
  399. Net_RawOutput(interPtr, headerPtr, gatherPtr, gatherLength)
  400.     Net_Interface    *interPtr;    /* The network interface. */
  401.     Address        headerPtr;    /* Packet header. */
  402.     Net_ScatterGather    *gatherPtr;    /* Specifies buffers containing the
  403.                      * pieces of the packet */
  404.     int         gatherLength;    /* Number of elements in gatherPtr[] */
  405. {
  406.     return (interPtr->output)(interPtr, headerPtr, gatherPtr, gatherLength, 
  407.         FALSE, (ReturnStatus *) NIL);
  408. }
  409.  
  410.  
  411. /*
  412.  *----------------------------------------------------------------------
  413.  *
  414.  * Net_RecvPoll --
  415.  *
  416.  *    See if a packet has come in.  If one has come in then it is assumed
  417.  *    that the packet processing routine will get called.  Thus this routine
  418.  *    does not return any value; it is up to the packet processing routine
  419.  *    to set some global state.  This is intended to be used by the
  420.  *    debugger.
  421.  *
  422.  * Results:
  423.  *    None.
  424.  *
  425.  * Side effects:
  426.  *    None.
  427.  *
  428.  *----------------------------------------------------------------------
  429.  */
  430.  
  431. void
  432. Net_RecvPoll(interPtr)
  433.     Net_Interface    *interPtr;    /* Network interface. */
  434. {
  435.     if (netDebug) {
  436.     printf("Net_RecvPoll\n");
  437.     }
  438.     (interPtr->intr)(interPtr, TRUE);
  439. }
  440.  
  441.  
  442. /*
  443.  *----------------------------------------------------------------------
  444.  *
  445.  * Net_RawOutputSync --
  446.  *
  447.  *     Send a packet on the network. Does not return until the packet
  448.  *    is actually sent.
  449.  *
  450.  * Results:
  451.  *    SUCCESS if the packet was sent correctly, otherwise a standard
  452.  *    Sprite return status.
  453.  *
  454.  * Side effects:
  455.  *    None.
  456.  *
  457.  *----------------------------------------------------------------------
  458.  */
  459. ReturnStatus
  460. Net_RawOutputSync(interPtr, headerPtr, gatherPtr, gatherLength)
  461.     Net_Interface    *interPtr;    /* Network interface. */
  462.     Address        headerPtr;    /* Packet header. */
  463.     Net_ScatterGather     *gatherPtr;    /* Specifies buffers containing the
  464.                      * pieces of the packet */
  465.     int         gatherLength;    /* Number of elements in gatherPtr[] */
  466. {
  467.     ReturnStatus    status;
  468.  
  469.     gatherPtr->mutexPtr = &(interPtr->syncOutputMutex);
  470.     gatherPtr->done = FALSE;
  471.  
  472.     MASTER_LOCK(&(interPtr->syncOutputMutex));
  473.  
  474.     status = (interPtr->output)(interPtr, headerPtr, gatherPtr, gatherLength, 
  475.     FALSE, &status);
  476.     if (status == SUCCESS) {
  477.     while (!gatherPtr->done) {
  478.         (void) Sync_SlowMasterWait(
  479.             (unsigned int)&(interPtr->syncOutputMutex), 
  480.             &(interPtr->syncOutputMutex), FALSE);
  481.     }
  482.     }
  483.     MASTER_UNLOCK(&(interPtr->syncOutputMutex));
  484.     return status;
  485. }
  486.  
  487. /*
  488.  *----------------------------------------------------------------------
  489.  *
  490.  * NetOutputWakeup --
  491.  *
  492.  *    Called to notify a waiter that a packet has been sent.  This is
  493.  *    hacked up now, as the argument is really a mutexPtr which
  494.  *    has been used as a raw event to wait on.  We have to use
  495.  *    the raw SlowBroadcast procedure because of this.
  496.  *
  497.  * Results:
  498.  *    None.
  499.  *
  500.  * Side effects:
  501.  *    None.
  502.  *
  503.  *----------------------------------------------------------------------
  504.  */
  505.  
  506. void
  507. NetOutputWakeup(mutexPtr)
  508.     Sync_Semaphore    *mutexPtr;    /* Mutex from scatter/gather struct */
  509. {
  510.     int waiting;
  511.  
  512.     /*
  513.      * FIX THIS.
  514.      */
  515.     if (dbg_UsingNetwork) {
  516.     return;
  517.     }
  518.  
  519. #if (MACH_MAX_NUM_PROCESSORS == 1) /* uniprocessor implementation */
  520.     (void) Sync_SlowBroadcast((unsigned int)mutexPtr, &waiting);
  521. #else     /* Mutiprocessor implementation */
  522.    /*
  523.     * Because the packet sent interrupt may come in before Net_Output
  524.     * has a chance to MasterWait and after Net_Output has checked the
  525.     * gatherPtr->done flag, the code should syncronize with the caller
  526.     * by obtaining the master lock.
  527.     */
  528.     MASTER_LOCK(mutexPtr);
  529.     (void) Sync_SlowBroadcast((unsigned int) mutexPtr, &waiting);    
  530.     MASTER_UNLOCK(mutexPtr);
  531. #endif
  532.     return;
  533. }
  534.  
  535.  
  536. /*
  537.  *----------------------------------------------------------------------
  538.  *
  539.  * Net_Intr --
  540.  *
  541.  *    The interrupt routine which is called when the ethernet chip 
  542.  *    interrupts the processor.  All this routine does is to branch
  543.  *    to the interrupt handler for the type of ethernet device
  544.  *    present on the machine.  The device driver, in turn, eventually
  545.  *    calls Net_Input to pass the packet to the correct protocol handler.
  546.  *
  547.  * Results:
  548.  *    None.
  549.  *
  550.  * Side effects:
  551.  *    None.
  552.  *
  553.  *----------------------------------------------------------------------
  554.  */
  555.  
  556. int
  557. Net_Intr(interPtr)
  558.     Net_Interface    *interPtr;    /* Network interface. */
  559. {
  560.     if (netDebug) {
  561.     printf("Received an interrupt on interface %s\n", interPtr->name);
  562.     }
  563.     (interPtr->intr)(interPtr, FALSE);
  564.     return 1;
  565. }
  566.  
  567. /*
  568.  *----------------------------------------------------------------------
  569.  *
  570.  * Net_Input --
  571.  *
  572.  *    A stub called by device drivers to pass off packets to protocols.
  573.  *    This could be a macro.
  574.  *
  575.  *    The packet handler called must copy the packet to private buffers.
  576.  *
  577.  *    TODO:
  578.  *        This routine, and the ones it calls, should not assume
  579.  *        that there is a packet header at the start of the
  580.  *        packet.  The header should be passed separately.
  581.  *
  582.  * Results:
  583.  *    None.
  584.  *
  585.  * Side effects:
  586.  *    None.  
  587.  *
  588.  *----------------------------------------------------------------------
  589.  */
  590.  
  591. void
  592. Net_Input(interPtr, packetPtr, packetLength)
  593.     Net_Interface *interPtr;    /* Network interface. */
  594.     Address packetPtr;        /* The packet. */
  595.     int packetLength;        /* The length of the packet. */
  596. {
  597.     int        headerSize;
  598.     int        packetType = NET_PACKET_UNKNOWN;
  599.  
  600. #if 0
  601.     printf("in Net_Input\n");
  602.     printf("Net_Input(0x%x, 0x%x, 0x%x)\n", interPtr, packetPtr, packetLength);
  603.     printf("netType = %08x\n", interPtr->netType);
  604. #endif
  605.  
  606.     if (netDebug) {
  607.     printf("Net_Input(0x%x, 0x%x, 0x%x) netType = %08x\n",
  608.         interPtr, packetPtr, packetLength, interPtr->netType);
  609.     }
  610.     switch(interPtr->netType) {
  611.     case NET_NETWORK_ETHER : {
  612.         Net_EtherHdr *etherHdrPtr;
  613.         int        type;
  614.         etherHdrPtr = (Net_EtherHdr *)packetPtr;
  615.         type = Net_NetToHostShort((unsigned short)
  616.             NET_ETHER_HDR_TYPE(*etherHdrPtr));
  617.         switch(type) {
  618.         case NET_ETHER_SPRITE:
  619.             packetType = NET_PACKET_SPRITE;
  620.             break;
  621.         case NET_ETHER_ARP:
  622.             packetType = NET_PACKET_ARP;
  623.             break;
  624.         case NET_ETHER_REVARP:
  625.             packetType = NET_PACKET_RARP;
  626.             break;
  627.         case NET_ETHER_SPRITE_DEBUG:
  628.             packetType = NET_PACKET_DEBUG;
  629.             break;
  630.         case NET_ETHER_IP:
  631.             packetType = NET_PACKET_IP;
  632.             break;
  633.         default:
  634.             packetType = NET_PACKET_UNKNOWN;
  635.             break;
  636.         }
  637.         break;
  638.     }
  639.     case NET_NETWORK_ULTRA: {
  640.         Net_UltraHeader    *ultraHdrPtr;
  641.         ultraHdrPtr = (Net_UltraHeader *) packetPtr;
  642.         if ((ultraHdrPtr->localAddress.tsapSize == 2) &&
  643.         (ultraHdrPtr->localAddress.tsap[0] == (unsigned char) 0xff) &&
  644.         (ultraHdrPtr->localAddress.tsap[1] == (unsigned char) 0xff)) {
  645.         packetType = NET_PACKET_SPRITE;
  646.         } else {
  647.         packetType = NET_PACKET_UNKNOWN;
  648.         }
  649.         break;
  650.     }
  651.     case NET_NETWORK_FDDI: {     /***/
  652.         Net_FDDIHdr *fddiHdrPtr;
  653.  
  654.         fddiHdrPtr = (Net_FDDIHdr *)packetPtr;
  655.         if (fddiHdrPtr->frameControl == NET_FDDI_SPRITE) {
  656.         packetType = NET_PACKET_SPRITE;
  657.         } else {
  658.         packetType = NET_PACKET_UNKNOWN;
  659.         }
  660.         break;
  661.     }
  662.     default: 
  663.         printf("Net_Input: invalid net type %d\n", interPtr->netType);
  664.     }
  665.     headerSize = net_NetworkHeaderSize[interPtr->netType];
  666.     if (dbg_UsingNetwork) {
  667.     /*
  668.      * If the kernel debugger is running it gets all the packets. We
  669.      * process ARP requests to allow hosts to talk to the debugger.
  670.      */
  671.     if (packetType == NET_PACKET_ARP) {
  672.             NetArpInput(interPtr, packetPtr, packetLength);
  673.     } else { 
  674.         Dbg_InputPacket(interPtr, packetPtr, packetLength);
  675.     }
  676.     return;
  677.     }
  678.     switch(packetType) {
  679.         case NET_PACKET_SPRITE:
  680.         if (netDebug) {
  681.         printf("Received a Sprite packet, calling Rpc_Dispatch\n");
  682.         }
  683.             Rpc_Dispatch(interPtr, NET_PROTO_RAW, packetPtr, 
  684.              (Address) (((char *) packetPtr) + headerSize), 
  685.              packetLength - headerSize);
  686.             break;
  687.  
  688.         case NET_PACKET_ARP:
  689.     case NET_PACKET_RARP:
  690.         /*
  691.          * The kernel gets first shot at ARP packets and then they are
  692.          * forward to tbe /dev/net device.
  693.          */
  694.         if (netDebug) {
  695.         if (packetType == NET_PACKET_ARP) {
  696.             printf("Received an ARP packet.\n");
  697.         } else {
  698.             printf("Received a RARP packet.\n");
  699.         }
  700.         }
  701.             NetArpInput(interPtr, packetPtr, packetLength);
  702.         if (interPtr->packetProc != NILPROC) {
  703.         (interPtr->packetProc)(interPtr, packetLength, packetPtr);
  704.         }
  705.         break;
  706.  
  707.         case NET_PACKET_DEBUG:
  708.         if (netDebug) {
  709.         printf("Received a debug packet.\n");
  710.         }
  711.             EnterDebugger(interPtr, packetPtr, packetLength);
  712.             break;
  713.  
  714.     case NET_PACKET_IP: {
  715.         register Net_IPHeader *ipHeaderPtr = 
  716.             (Net_IPHeader *) (packetPtr + headerSize);
  717.         /*
  718.          * The kernel steals IP packets with the Sprite RPC protocol number.
  719.          */
  720.         if (netDebug) {
  721.         printf("Received an IP packet.\n");
  722.         }
  723.         if ( (packetLength > sizeof(Net_IPHeader)+headerSize) && 
  724.              (ipHeaderPtr->protocol == NET_IP_PROTOCOL_SPRITE)) {
  725.         int    headerLenInBytes;
  726.         int    totalLenInBytes;
  727.         headerLenInBytes = ipHeaderPtr->headerLen * 4;
  728.         totalLenInBytes = Net_NetToHostShort(ipHeaderPtr->totalLen);
  729.         /*
  730.          * Validate the packet. We toss out the following cases:
  731.          * 1) Runt packets.
  732.          * 2) Bad checksums.
  733.          * 3) Fragments.
  734.          * Since we sent the packets with dont fragment set we 
  735.          * shouldn't get any fragments.
  736.          */
  737.         if ((headerLenInBytes >= sizeof(Net_IPHeader)) &&
  738.              (totalLenInBytes > headerLenInBytes) &&
  739.              (totalLenInBytes <= (packetLength-headerSize)) &&
  740.              (Net_InetChecksum(headerLenInBytes, (Address)ipHeaderPtr)
  741.                                 == 0)) {
  742.  
  743.             SWAP_FRAG_OFFSET_NET_TO_HOST(ipHeaderPtr);
  744.             if((!(ipHeaderPtr->flags & NET_IP_MORE_FRAGS)) &&
  745.               (ipHeaderPtr->fragOffset == 0)) {
  746.             if (netDebug) {
  747.                 printf(
  748.             "Received a Sprite IP packet, calling Rpc_Dispatch\n");
  749.             }
  750.             Rpc_Dispatch(interPtr, NET_PROTO_INET, packetPtr, 
  751.                    (Address)(((char *) ipHeaderPtr) + headerLenInBytes),
  752.                      totalLenInBytes-headerLenInBytes);
  753.              }
  754.         }
  755.  
  756.         } else {
  757.  
  758.         if (interPtr->packetProc != NILPROC) {
  759.             (interPtr->packetProc)(interPtr, packetLength, packetPtr);
  760.         }
  761.         }
  762.         break;
  763.     }
  764.     default:
  765.         if (netDebug) {
  766.         printf("Received a packet with unknown type 0x%x.\n",
  767.             packetType);
  768.         }
  769.         if (interPtr->packetProc != NILPROC) {
  770.         (interPtr->packetProc)(interPtr, packetLength, packetPtr);
  771.         }
  772.         break;
  773.     }
  774.     return;
  775. }
  776.  
  777.  
  778. /*
  779.  *----------------------------------------------------------------------
  780.  *
  781.  * EnterDebugger --
  782.  *
  783.  *    Processes the special NET_ETHER_SPRITE_DEBUG packet type.
  784.  *    Prints the data in the packet (which is the hostname of the sender)
  785.  *    and then enters the debugger. The format of data in the packet is:
  786.  *     1) size of sender's name in bytes (4 bytes),
  787.  *     2) the sender's name (max 100 bytes).
  788.  *
  789.  * Results:
  790.  *    None.
  791.  *
  792.  * Side effects:
  793.  *    Enters the debugger.
  794.  *
  795.  *----------------------------------------------------------------------
  796.  */
  797.  
  798. /* ARGSUSED */
  799. static void
  800. EnterDebugger(interPtr, packetPtr, packetLength)
  801.     Net_Interface    *interPtr;
  802.     Address packetPtr;
  803.     int packetLength;
  804. {
  805.     char *name;
  806.     unsigned int  len;
  807.  
  808.     packetPtr += net_NetworkHeaderSize[interPtr->netType];
  809.     /*
  810.      * Copy the length out of the packet into a correctly aligned integer.
  811.      * Correct its byte order.
  812.      */
  813.     bcopy( packetPtr, (Address) &len, sizeof(len));
  814.  
  815.     len = Net_NetToHostInt(len);
  816.  
  817.     /*
  818.      * Validate the data length and make sure the name is null-terminated.
  819.      */
  820.     if (len < 100) {
  821.     name = (char *) (packetPtr + sizeof(len));
  822.     name[len] = '\0';
  823.     printf("\n*** Got a debugger packet from %s ***\n", name);
  824.     } else {
  825.     printf("\n*** Got a debugger packet ***\n");
  826.     }
  827.  
  828.     DBG_CALL;
  829.     return;
  830. }
  831.  
  832. /*
  833.  *----------------------------------------------------------------------
  834.  *
  835.  * Net_GetInterface --
  836.  *
  837.  *    Returns a pointer to the interface structure with the
  838.  *    given number and type.
  839.  *
  840.  * Results:
  841.  *    A pointer to a Net_Interface if one with the given number
  842.  *    exists, NIL otherwise.
  843.  *
  844.  * Side effects:
  845.  *    None.
  846.  *
  847.  *----------------------------------------------------------------------
  848.  */
  849.  
  850. Net_Interface *
  851. Net_GetInterface(netType, number)
  852.     Net_NetworkType    netType;    /* Type of interface. */
  853.     int            number;        /* Number of interface. */
  854. {
  855.     Net_Interface    *interPtr;
  856.     register int    i;
  857.  
  858.     interPtr = (Net_Interface *) NIL;
  859.     for (i = 0; i < netNumInterfaces; i++) {
  860.     if (netInterfaces[i]->netType == netType &&
  861.         netInterfaces[i]->number == number) {
  862.         interPtr = netInterfaces[i];
  863.         break;
  864.     }
  865.     }
  866.     return interPtr;
  867. }
  868. /*
  869.  *----------------------------------------------------------------------
  870.  *
  871.  * Net_GetInterfaceByAddr --
  872.  *
  873.  *    Returns a pointer to the interface whose address matches the 
  874.  *     given address. If the address is an IP address then the IP
  875.  *    address for the interface had better be set.
  876.  *
  877.  * Results:
  878.  *    A pointer to the desired Net_Interface if one is found, NIL
  879.  *    otherwise.
  880.  *
  881.  * Side effects:
  882.  *    None.
  883.  *
  884.  *----------------------------------------------------------------------
  885.  */
  886.  
  887. Net_Interface *
  888. Net_GetInterfaceByAddr(netAddressPtr)
  889.     Net_Address        *netAddressPtr;    /* Address to use. */
  890. {
  891.     register int    i, j;
  892.  
  893.     for (i = 0; i < netNumInterfaces; i++) {
  894.     for (j = 0; j < NET_MAX_PROTOCOLS; j++) {
  895.         if (!Net_AddrCmp(netAddressPtr, &netInterfaces[i]->netAddress[j])) {
  896.         return netInterfaces[i];
  897.         }
  898.     }
  899.     }
  900.     return (Net_Interface *) NIL;
  901. }
  902.  
  903. /*
  904.  *----------------------------------------------------------------------
  905.  *
  906.  * Net_NextInterface --
  907.  *
  908.  *     This routine can be used to iterate through all network
  909.  *    interfaces, regardless of type.  The parameter 'index'
  910.  *    is used to keep track of where we are in the interaction.
  911.  *    A pointer will be returned to first interface whose index
  912.  *    is equal to or greater than 'index' and that is running.
  913.  *    The 'index' parameter will be set to the index of the
  914.  *    interface upon return.  
  915.  *
  916.  * Results:
  917.  *    A pointer to the first interface whose number if greater than
  918.  *    or equal to the contents of indexPtr and is running. NIL
  919.  *    if no such interface exists.
  920.  *
  921.  * Side effects:
  922.  *    None.
  923.  *
  924.  *----------------------------------------------------------------------
  925.  */
  926.  
  927. Net_Interface *
  928. Net_NextInterface(running, indexPtr)
  929.     Boolean        running;    /* TRUE => returned interface    
  930.                      * must be in running state. */
  931.     int            *indexPtr;    /* Ptr to index to use. */
  932. {
  933.     register int    i;
  934.  
  935.     for (i = *indexPtr; i < netNumInterfaces; i++) {
  936.     if (netDebug) {
  937.         printf("i = %d, name = %s, running = %d\n", i, 
  938.         netInterfaces[i]->name, 
  939.         netInterfaces[i]->flags & NET_IFLAGS_RUNNING);
  940.     }
  941.     if (!running || netInterfaces[i]->flags & NET_IFLAGS_RUNNING) {
  942.         *indexPtr = i;
  943.         return netInterfaces[i];
  944.     }
  945.     }
  946.     return (Net_Interface *) NIL;
  947. }
  948.  
  949. /*
  950.  *----------------------------------------------------------------------
  951.  *
  952.  * Net_SetPacketHandler --
  953.  *
  954.  *    Routine to register a callback for each packet received
  955.  *    on a particular network interface.
  956.  *    Right now the Net_Input routine knows about the different
  957.  *     types of packets and knows which routines to call.  This
  958.  *    routine is used to set the callback for generic packets
  959.  *    so that the dev module sees them. 
  960.  *
  961.  *    The handler parameter should have the following definition:
  962.  *        void    handler(interPtr, packetPtr, size)
  963.  *            Net_Interface    *interPtr; 
  964.  *            Address        packetPtr; 
  965.  *            int        size;       
  966.  *
  967.  *    TODO:  It would probably be nice to classify packets (rpc, ip,
  968.  *        ether, etc) and register interest in the different
  969.  *        classifications. That would make Net_Input more
  970.  *        general.
  971.  *
  972.  * Results:
  973.  *    None.
  974.  *
  975.  * Side effects:
  976.  *    The function parameter will be called for all 'normal' network
  977.  *    packets.
  978.  *
  979.  *----------------------------------------------------------------------
  980.  */
  981.  
  982. void
  983. Net_SetPacketHandler(interPtr, handler)
  984.     Net_Interface    *interPtr;    /* The interface. */
  985.     void        (*handler)();    /* Packet handling routine. */
  986. {
  987.     interPtr->packetProc = handler;
  988. }
  989.  
  990. /*
  991.  *----------------------------------------------------------------------
  992.  *
  993.  * Net_RemovePacketHandler --
  994.  *
  995.  *    Routine to remove a packet handler callback procedure.
  996.  *
  997.  * Results:
  998.  *    None.
  999.  *
  1000.  * Side effects:
  1001.  *    None.
  1002.  *
  1003.  *----------------------------------------------------------------------
  1004.  */
  1005.  
  1006. void
  1007. Net_RemovePacketHandler(interPtr)
  1008.     Net_Interface    *interPtr;    /* The interface. */
  1009. {
  1010.     interPtr->packetProc = NILPROC;
  1011. }
  1012.  
  1013. /*
  1014.  *----------------------------------------------------------------------
  1015.  *
  1016.  * Net_GetStats --
  1017.  *
  1018.  *    Returns the event statistics for the various network 
  1019.  *    interfaces.  The sum of the stats for all interfaces of the
  1020.  *    given type is returned.
  1021.  *
  1022.  * Results:
  1023.  *    SUCCESS if the statistics are returned, an error code otherwise
  1024.  *
  1025.  * Side effects:
  1026.  *    None.
  1027.  *
  1028.  *----------------------------------------------------------------------
  1029.  */
  1030.  
  1031. ReturnStatus
  1032. Net_GetStats(netType, statPtr)
  1033.     Net_NetworkType    netType;     /* Type of interfaces to get stats
  1034.                      * for. */
  1035.     Net_Stats        *statPtr;    /* Statistics to fill in. */ 
  1036. {
  1037.     int            i;
  1038.     ReturnStatus    status = SUCCESS;
  1039.     Net_Stats        tmpStats;
  1040.  
  1041.     bzero((char *) statPtr, sizeof(Net_Stats));
  1042.     for (i = 0; i < netNumInterfaces; i++) {
  1043.     if ((netInterfaces[i]->flags & NET_IFLAGS_RUNNING) &&
  1044.         (netInterfaces[i]->netType == netType)) {
  1045.         status = (netInterfaces[i]->getStats)(netInterfaces[i], &tmpStats);
  1046.         if (status != SUCCESS) {
  1047.         break;
  1048.         }
  1049.         NetAddStats(&tmpStats, statPtr, statPtr);
  1050.     }
  1051.     }
  1052.     return status;
  1053. }
  1054.  
  1055.  
  1056. /*
  1057.  *----------------------------------------------------------------------
  1058.  *
  1059.  * NetAddStats --
  1060.  *
  1061.  *    Add two stats structures together. This routine assumes that
  1062.  *    the structures are composed of only integers.
  1063.  *
  1064.  * Results:
  1065.  *    None.
  1066.  *
  1067.  * Side effects:
  1068.  *    None.
  1069.  *
  1070.  *----------------------------------------------------------------------
  1071.  */
  1072.  
  1073. static void
  1074. NetAddStats(aPtr, bPtr, sumPtr)
  1075.     Net_Stats *aPtr;            /* First addend. */
  1076.     Net_Stats *bPtr;            /* Second addend. */
  1077.     Net_Stats *sumPtr;            /* The sum of the two. */
  1078. {
  1079.     Net_Stats        tmp;
  1080.     int            i;
  1081.  
  1082.     bzero((char *) &tmp, sizeof(tmp));
  1083.     for (i = 0; i < sizeof(Net_Stats) / sizeof(int); i++) {
  1084.     ((int *) &tmp)[i] = ((int *) aPtr)[i] + ((int *) bPtr)[i];
  1085.     }
  1086.     bcopy((char *) &tmp, (char *) sumPtr, sizeof(Net_Stats));
  1087. }
  1088.  
  1089.